package p.ithorns.tools.excel;

import org.apache.commons.collections4.CollectionUtils;
import org.hibernate.validator.HibernateValidator;

import javax.validation.*;
import javax.validation.metadata.BeanDescriptor;
import javax.validation.metadata.ConstraintDescriptor;
import javax.validation.metadata.PropertyDescriptor;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;

/**
 * Validators
 *
 * @author HtL
 * @date 2024/8/2 12:23
 * @since 1.0.0
 */
public class Validators {

    /**
     * 字段校验器
     */
    private final static Validator VALIDATOR;

    /**
     * 校验消息模版
     */
    private final static MessageInterpolator INTERPOLATOR;

    static {
        try (ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class).configure()
                // 快速失败模式
                .failFast(false)
                .buildValidatorFactory()) {
            VALIDATOR = validatorFactory.getValidator();
            INTERPOLATOR = validatorFactory.getMessageInterpolator();
        }

//        HashSet<Locale> locales = Sets.newHashSet(Locale.getDefault());
//        PlatformResourceBundleLocator locator =
//                new PlatformResourceBundleLocator(ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, locales);
//        MessageInterpolator messageInterpolator = new ResourceBundleMessageInterpolator(locator, true);
    }

    public static Validator getValidator() {
        return VALIDATOR;
    }

    public static Map<String, Set<ConstraintDescriptor<?>>> getConstraintMap(Class<?> clazz) {
        BeanDescriptor beanDescriptor = Validators.getValidator().getConstraintsForClass(clazz);
        Set<PropertyDescriptor> properties = beanDescriptor.getConstrainedProperties();
        Map<String, Set<ConstraintDescriptor<?>>> map = new HashMap<>(properties.size());

        for (PropertyDescriptor pd : properties) {
            String propertyName = pd.getPropertyName();
            Set<ConstraintDescriptor<?>> constraints = pd.getConstraintDescriptors();
            map.put(propertyName, constraints);
        }
        return map;
    }

    public static <T> Set<ConstraintViolation<T>> validate(T t) {
        return VALIDATOR.validate(t);
    }

    public static String interpolate(String messageTemplate, MessageInterpolator.Context context) {
        return INTERPOLATOR.interpolate(messageTemplate, context);
    }

    public static <T> void validate(T t, BiConsumer<String, String> consumer) {
        Set<ConstraintViolation<T>> constraintSet = VALIDATOR.validate(t);
        if (CollectionUtils.isNotEmpty(constraintSet)) {
            constraintSet.forEach(cv -> {
                // 字段名
                Path property = cv.getPropertyPath();
                String filedName = property.toString();
                String message = cv.getMessage();
                if (null != consumer) {
                    consumer.accept(filedName, message);
                }
            });
        }
    }

    public static Set<ConstraintDescriptor<?>> getDescriptors(Class<?> clazz) {
        // 获取注解描述符
        BeanDescriptor descriptor = VALIDATOR.getConstraintsForClass(clazz);
//        constraintsForClass.getConstraintsForProperty("propertyName")
        return descriptor.getConstraintDescriptors();
    }

    //    public static <T> void validate(T t) {
//        Set<ConstraintViolation<T>> constraintSet = VALIDATOR.validate(t);
//        if (CollectionUtils.isNotEmpty(constraintSet)) {
//            constraintSet.forEach(cv -> {
//                // 字段名
//                String filedName = cv.getPropertyPath().toString();
//                String message = cv.getMessage();
//
//                String msg = MessageFormat.format("{0} -> {1}", filedName, message);
//                throw new ValidationException(msg);
//            });
//        }
//    }

}